package cn.fntop.config;

import cn.fntop.context.DsDdlApplicationRunner;
import cn.fntop.filter.SqlFilterArgumentResolver;
import cn.fntop.handler.InjectionMetaObjectHandler;
import cn.fntop.handler.TenantHandler;
import cn.fntop.interceptor.DataPermissionInterceptor;
import cn.hutool.core.net.NetUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.DdlApplicationRunner;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.extension.ddl.IDdl;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;

import java.util.List;

/**
 * MybatisPlus 插件配置
 */
@Slf4j
@Configuration
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class MybatisPlusConfig {

    /**
     * mybatis plus 拦截器配置
     *
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(TenantConfigProperties tenantConfigProperties, List<HandlerMethodArgumentResolver> argumentResolvers) {
        log.info(">>>>>>>>>>> 加载mybatis-plus 拦截器 >>>>>>>>>>> ");
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 多租户插件
        if (tenantConfigProperties.getEnabled()) {
            log.info("加载mybatis-plus 租户插件（必须放第一位）");
            TenantLineInnerInterceptor tenantLineInnerInterceptor = new TenantLineInnerInterceptor();
            tenantLineInnerInterceptor.setTenantLineHandler(new TenantHandler(tenantConfigProperties));
            interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
        }
        // 数据权限插件

        // 分页插件
        log.info("加载mybatis-plus 分页插件");
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        paginationInnerInterceptor.setOverflow(true);
        // 设置最大单页限制数量，默认 500 条，-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        log.info("加载mybatis-plus 乐观锁插件");
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        log.info("加载mybatis-plus 数据权限插件");
//        interceptor.addInnerInterceptor(dataPermissionInterceptor());
        log.info(">>>>>>>>>>> 加载mybatis-plus 拦截器 >>>>>>>>>>> ");

        initArgumentResolvers(argumentResolvers);
        return interceptor;
    }

    /**
     * 元对象字段填充控制器
     */
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new InjectionMetaObjectHandler();
    }

    /**
     * 使用网卡信息绑定雪花生成器
     * 防止集群雪花ID重复
     */
    @Bean
    public IdentifierGenerator idGenerator() {
        return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
    }


    /**
     * 增加请求参数解析器，对请求中的参数注入SQL 检查
     *
     * @param argumentResolvers
     */
    public void initArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        log.info(">>>>>>>>>>>>>> 对请求中的参数注入SQL 检查 >>>>>>>>>>>>>> ");
        log.info("添加分页参数解析器");
        argumentResolvers.add(new SqlFilterArgumentResolver());
        log.info(">>>>>>>>>>>>>> 对请求中的参数注入SQL 检查 >>>>>>>>>>>>>> ");
    }

    /**
     * 默认数据权限处理器
     * @return
     */
    /**
     * 数据权限拦截器
     */
    @Bean
    public DataPermissionInterceptor dataPermissionInterceptor() {
        return new DataPermissionInterceptor();
    }

    /**
     * 自动维护脚本升级
     *
     * @param ddlList
     * @return
     */
    @Bean
    public DdlApplicationRunner ddlApplicationRunner(@Autowired(required = false) List<IDdl> ddlList) {
        return new DsDdlApplicationRunner(ddlList);
    }
}
